#include "WubiUI.h"

#include <FL/fl_ask.H>
#include "utils/file_chooser.h"
#include "utils/ui_utils.h"
#include <fstream>
#include <FL/fl_utf8.h>
#include <filesystem>

WubiUI::WubiUI():
_code_table_edit_ui(&_ui_ipc_client)
{
    _current_scheme_id = 0;
    _last_selected_scheme_id = 0;
}
WubiUI::~WubiUI()
{
    _ui_ipc_client.release();
}



void WubiUI::reloadScheme() // 重新加载方案数据
{
    // 处理方案标签页切换逻辑
    IpcMsgHelper *msg_helper = _ui_ipc_client.getMsgHelper();
    _schemes.clear(); // 清空方案列表
    _current_scheme_id = 0;
    int selected_index = 0;
    do
    {
        if (!msg_helper->getAllSchemes(_schemes))
            break;

        // 获取当前激活的方案id
        msg_helper->getCurrentSchemeId(_current_scheme_id);

        // 清空浏览器
        _main_window.scheme_browser->clear();
        // 遍历方案列表并添加到浏览器
        for (int i = 0; i < _schemes.size(); i++)
        {
            const UIBaseInfo &scheme = _schemes[i];
            const char *head = "";
            if (scheme.id == _current_scheme_id){
                head = "*"; // 如果当前方案是选中的方案，则在名称前加上*
                selected_index = i + 1; //默认选中
            }
            _main_window.scheme_browser->add((head + scheme.name).c_str(), this);
        }
        // 如果没有选中方案就选择第一个
        if(selected_index == 0) {
            if(_schemes.size() > 0) {
                selected_index = 1; // 默认选中第一个 
            }
        }

        // 默认选中方案
        if(selected_index > 0) {
            _main_window.scheme_browser->select(selected_index); // 选中默认方案
            onSchemeItemClick( _main_window.scheme_browser, this); // 触发方案选择事件
        }

        _main_window.box_notconnet->hide(); // 隐藏网络连接失败提示
        return;
    } while (0);
    // 显示网络连接失败提示
    _main_window.box_notconnet->show();
}

void WubiUI::init()
{
    _ui_ipc_client.init();

    _code_table_edit_ui.init();

    _main_window.make_window();
    _add_scheme_window.make_window();
    _add_code_table_window.make_window();

    // 隐藏网络连接失败提示
    _main_window.box_notconnet->hide();

    // 初始化taba切换
    _main_window.ui_tab->callback(onTabChage, this);
    // 单选
    _main_window.scheme_browser->type(FL_HOLD_BROWSER);
    _main_window.scheme_browser->callback(onSchemeItemClick, this);
    _main_window.codetable_browser->type(FL_HOLD_BROWSER); // 单选

    _main_window.box_wordCode->label("");
    _main_window.input_wordToCode->value("");
    _main_window.btn_wordToCode->callback(onSearchWordCode, this); // 编码反查

    // 设置添加码表窗口回调
    if (_add_code_table_window.btn_confirm)
    {
        _add_code_table_window.btn_confirm->callback(onAddCodeTableConfirm, this);
    }
    if (_add_code_table_window.btn_cancel)
    {
        _add_code_table_window.btn_cancel->callback(onAddCodeTableCancel, this);
    }
    if (_add_code_table_window.btn_import)
    {
        _add_code_table_window.btn_import->callback(onImportFile, this);
    }

    // 设置添加方案窗口回调
    if (_add_scheme_window.btn_add)
    {
        _add_scheme_window.btn_add->callback(onAddSchemeConfirm, this);
    }
    if (_add_scheme_window.btn_cancel)
    {
        _add_scheme_window.btn_cancel->callback(onAddSchemeCancel, this);
    }

    // 设置主窗口按钮回调
    if (_main_window.btn_active)
    {
        _main_window.btn_active->callback(onActiveScheme, this);
    }
    if (_main_window.btn_scheme_add)
    {
        _main_window.btn_scheme_add->callback(onShowAddScheme, this);
    }
    if (_main_window.btn_codetable_add)
    {
        _main_window.btn_codetable_add->callback(onShowAddCodeTable, this);
    }
    if (_main_window.btn_codetable_delete)
    {
        _main_window.btn_codetable_delete->callback(onDeleteCodeTable, this);
    }
    if (_main_window.btn_codetable_up)
    {
        _main_window.btn_codetable_up->callback(onMoveUpCodeTable, this);
    }
    if (_main_window.btn_codetable_down)
    {
        _main_window.btn_codetable_down->callback(onMoveDownCodeTable, this);
    }
    if (_main_window.btn_codetable_reload)
    {
        _main_window.btn_codetable_reload->callback(onReloadCodeTable, this);
    }
    if (_main_window.btn_codetable_edit)
    {
        _main_window.btn_codetable_edit->callback(onEditCodeTable, this);
    }
    if (_main_window.btn_scheme_remove)
    {
        _main_window.btn_scheme_remove->callback(onRemoveScheme, this);
    }
    _main_window.btn_codetable_enable->callback(onCodeTableEnable, this);
    _main_window.btn_codetable_export->callback(onExportCodeTable, this); // 导出码表
}

// 新增回调函数实现
void WubiUI::onAddCodeTableConfirm(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);

    do{
        const char *file_path = self->_add_code_table_window.text_file->value(); // 获取文件路径
        const char *table_name = self->_add_code_table_window.input_name->value(); // 获取文件路径
        if (file_path == NULL || strlen(file_path) == 0) // 没有选择文件
            break;
        if  (table_name == NULL || strlen(table_name) == 0)
            break;
        if(self->_last_selected_scheme_id == 0) // 没有选中方案
            break;
        // 调用IPC添加码表
        IpcMsgHelper *msg_helper = self->_ui_ipc_client.getMsgHelper();
        
        // 检查文件路径是否存在
        char local_path[_MAX_PATH] = {0};
        {
            int ret = fl_utf8locale();
            if(!ret){
                fl_utf8to_mb(file_path,strlen(file_path),local_path,sizeof(local_path));
                file_path = local_path;
            }
            std::ifstream file(file_path);
            if (!file.is_open()) { // 打开文件失败
                fl_message("打开文件失败:%s", file_path);
                return;
            }
            file.close();
        }
        

        
        unsigned int newid = 0;
        if (msg_helper->addCodeTable(self->_last_selected_scheme_id,table_name,file_path, newid)){
            self->_code_tables.push_back(UIBaseInfo{newid, table_name,true});
            //新加入的码表都是激活状态
            self->_main_window.codetable_browser->add((std::string("*") + table_name).c_str());
            fl_message("添加码表成功,id:%u", newid);
        }else{
            fl_message("添加码表失败");
        }
    }while(0);
    
    // 处理码表确认逻辑
    self->_add_code_table_window.main_window->hide();
}

void WubiUI::onAddCodeTableCancel(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    self->_add_code_table_window.main_window->hide();
}

void WubiUI::onAddSchemeConfirm(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    // 处理方案添加逻辑
    const char *scheme_name = self->_add_scheme_window.scheme_name->value();
    if (scheme_name && strlen(scheme_name) > 0)
    {
        // 调用IPC添加方案
        IpcMsgHelper *msg_helper = self->_ui_ipc_client.getMsgHelper();
        unsigned int newid = 0;
        if (msg_helper->createScheme(scheme_name, newid))
        {
            fl_message("添加方案成功,id:%u", newid);
            // 重新加载方案数据
            self->reloadScheme();
        }
        else
        {
            fl_message("添加方案失败");
        }
    }
    self->_add_scheme_window.main_window->hide();
}

void WubiUI::onAddSchemeCancel(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    self->_add_scheme_window.main_window->hide();
}

void WubiUI::onActiveScheme(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    // 处理激活方案逻辑
    int index = self->_main_window.scheme_browser->value(); // 获取当前选中项的索引
    --index;                                                // 获取的索引从1开始，需要减1
    if (index >= 0 && index < self->_schemes.size())
    {
        const UIBaseInfo &scheme = self->_schemes[index]; // 获取选中的方案信息

        if (scheme.id == self->_current_scheme_id) // 如果当前方案已经是选中的方案，则不做任何操作
            return;

        // 调用IPC删除方案
        IpcMsgHelper *msg_helper = self->_ui_ipc_client.getMsgHelper();
        msg_helper->setCurrentSchemeId(scheme.id);
        self->reloadScheme();
    }
}

void WubiUI::onShowAddScheme(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    UIUtils::showFlDoubleWindow(self->_add_scheme_window.main_window);
}

void WubiUI::onShowAddCodeTable(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    UIUtils::showFlDoubleWindow(self->_add_code_table_window.main_window);
}

void WubiUI::onImportFile(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);

    const char *file_name = codetable_file_chooser("选择一个文件", "*.txt", nullptr, nullptr);
    if (file_name)
    {
        self->_add_code_table_window.text_file->value(file_name);
       // fl_message("选择的文件是: %s", file_name);
    }
}

void WubiUI::onTabChage(Fl_Widget *w, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    Fl_Tabs *tabs = (Fl_Tabs *)w;
    if (tabs->value() == self->_main_window.group_scheme)
    {
        self->reloadScheme();
    }
}

void WubiUI::onSchemeItemClick(Fl_Widget *w, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    Fl_Browser *browser = (Fl_Browser *)w;
    int index = browser->value(); // 获取当前选中项的索引
    --index;                      // 获取的索引从1开始，需要减1
    if (index < 0 || index >= self->_schemes.size())
        return;

    const UIBaseInfo &scheme = self->_schemes[index]; // 获取选中的方案信息
    if (scheme.id == self->_last_selected_scheme_id)  // 如果当前方案已经是选中的方案，则不做任何操作
        return;

 
    IpcMsgHelper *msg_helper = self->_ui_ipc_client.getMsgHelper();

    self->_code_tables.clear(); // 清空码表列表
    self->_last_selected_scheme_id = scheme.id;    // 记录上次选中的方案id
    //显示码表名称
    self->_main_window.codetable_browser->label(scheme.name.c_str());

    if (msg_helper->getCodeTables(scheme.id, self->_code_tables))
    {
        self->_main_window.codetable_browser->clear(); // 清空码表列表
        // 遍历码表列表并添加到浏览器
        for (const auto &table : self->_code_tables)
        {
            const char *head = "";
            if (table.enable) // 如果码表启用，则在名称前加上*
                head = "*";
            self->_main_window.codetable_browser->add((head+table.name).c_str()); // 假设table.name是码表的名称，你需要根据实际情况修改这里的代码
        }
    }else{
        fl_message("获取码表失败");
    }
}

void WubiUI::show()
{
    // 先获取屏幕尺寸和窗口尺寸
    UIUtils::showFlDoubleWindow(_main_window.main_window); // 显示主窗口
}

// 新增回调函数实现
void WubiUI::onDeleteCodeTable(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    // 处理删除码表逻辑（需获取当前选中项）
    int index = self->_main_window.codetable_browser->value(); // 获取当前选中项的索引
    --index;                                                // 获取的索引从1开始，需要减1
    if (index < 0 || index >= self->_code_tables.size())
        return;

    const UIBaseInfo &table = self->_code_tables[index]; // 获取选中的码表信息
    if(fl_choice("确定删除码表['%s']吗？", "否", "是", NULL, table.name.c_str()) != 1) // 弹出确认对话框
        return; // 如果用户取消删除，则返回

    auto msg_helper = self->_ui_ipc_client.getMsgHelper();
    if (msg_helper->removeCodeTable(self->_last_selected_scheme_id, table.id)) // 调用IPC删除码表
    {
        self->_code_tables.erase(self->_code_tables.begin() + index); // 从列表中删除
        self->_main_window.codetable_browser->remove(index + 1);       // 从浏览器中删除
        fl_message("删除码表成功"); 
    }
}

void WubiUI::onCodeTableEnable(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    int index = self->_main_window.codetable_browser->value() - 1;
    if (index < 0 || index >= self->_code_tables.size())
        return;

    UIBaseInfo &table = self->_code_tables[index];
    bool newEnable = !table.enable;
    
    // 调用IPC设置启用状态
    if (self->_ui_ipc_client.getMsgHelper()->setCodeTableEnable(table.id, newEnable)) {
        table.enable = newEnable;
        // 更新浏览器显示状态
        std::string newName = (newEnable ? "*" : "") + table.name;
        self->_main_window.codetable_browser->text(index + 1, newName.c_str());
    }
}

void WubiUI::onMoveUpCodeTable(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    int index = self->_main_window.codetable_browser->value() - 1;
    if (index <= 0 || index >= self->_code_tables.size())
        return;

    // 交换相邻两个码表
    unsigned int id1 = self->_code_tables[index].id;
    unsigned int id2 = self->_code_tables[index-1].id;
    
    if (self->_ui_ipc_client.getMsgHelper()->swapCodeTableOrder(id1, id2)) {
        std::swap(self->_code_tables[index], self->_code_tables[index-1]);
        // 交换浏览器中的显示顺序
        self->_main_window.codetable_browser->swap(index, index + 1);
        self->_main_window.codetable_browser->select(index);
    }
}

void WubiUI::onMoveDownCodeTable(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    int index = self->_main_window.codetable_browser->value() - 1;
    if (index < 0 || index >= self->_code_tables.size() - 1)
        return;

    // 交换相邻两个码表
    unsigned int id1 = self->_code_tables[index].id;
    unsigned int id2 = self->_code_tables[index+1].id;
    
    if (self->_ui_ipc_client.getMsgHelper()->swapCodeTableOrder(id1, id2)) {
        std::swap(self->_code_tables[index], self->_code_tables[index+1]);
        // 交换浏览器中的显示顺序
        self->_main_window.codetable_browser->swap(index + 1, index + 2);
        self->_main_window.codetable_browser->select(index + 2);
    }
}

void WubiUI::onReloadCodeTable(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    // 处理重新加载码表逻辑
    auto msg_helper = self->_ui_ipc_client.getMsgHelper();
    if(msg_helper->reloadWordDic())
    {
        fl_message("重新加载码表成功");
    }

}

void WubiUI::onEditCodeTable(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    // 显示编辑码表窗口
    int index = self->_main_window.codetable_browser->value(); // 获取当前选中项的索引
    --index;                                                // 获取的索引从1开始，需要减1
    if (index < 0 || index >= self->_code_tables.size()){
        fl_message("没有选中码表");
        return;
    }

    const UIBaseInfo &table = self->_code_tables[index]; // 获取选中的码表信息
    self->_code_table_edit_ui.show(table.id, table.name);
    
}

void WubiUI::onRemoveScheme(Fl_Widget *, void *userdata)
{
    auto self = static_cast<WubiUI *>(userdata);
    // 处理删除方案逻辑
    int index = self->_main_window.scheme_browser->value(); // 获取当前选中项的索引
    --index;                                                // 获取的索引从1开始，需要减1
    if (index >= 0 && index < self->_schemes.size())
    {
        const UIBaseInfo &scheme = self->_schemes[index]; // 获取选中的方案信息
        if (fl_choice("确定删除方案['%s']吗？", "否", "是", NULL, scheme.name.c_str()) == 1)
        { // 弹出确认对话框
            // 调用IPC删除方案
            IpcMsgHelper *msg_helper = self->_ui_ipc_client.getMsgHelper();
            if (msg_helper->deleteScheme(scheme.id))
            {
                fl_message("删除方案成功");
                // 重新加载方案数据
                self->reloadScheme();

                self->_main_window.codetable_browser->clear(); // 清空码表列表
                self->_last_selected_scheme_id = 0;
            }
        }
    }
}

void WubiUI::onSearchWordCode(Fl_Widget*, void* userdata){
    auto self = static_cast<WubiUI*>(userdata);
    const std::string word = self->_main_window.input_wordToCode->value();
    if(word.empty()) {
        fl_message("请输入要查询的词语");
        return;
    }

    std::vector<std::string> codes;
    if(self->_ui_ipc_client.getMsgHelper()->getCodeByWord(word, codes)) {
        std::string result = "编码列表: ";
        for(const auto& code : codes) {
            result += code + " ";
        }
        self->_main_window.box_wordCode->copy_label(result.c_str());
    } else {
        fl_message("编码反查失败，请检查输入法服务是否启动");
    }
}
void WubiUI::onExportCodeTable(Fl_Widget*, void* userdata){
    auto self = static_cast<WubiUI*>(userdata);
    int index = self->_main_window.codetable_browser->value() - 1;
    if(index < 0 || index >= self->_code_tables.size()) {
        fl_message("请先选择要导出的码表");
        return;
    }

    const UIBaseInfo& table = self->_code_tables[index];

    // 创建文件夹的路径
    std::filesystem::path dir_path = "../export/";
    // 创建文件夹
    try {
        if (!std::filesystem::exists(dir_path)) {
            std::filesystem::create_directories(dir_path);
        } 
    } catch (std::filesystem::filesystem_error& e) {
        fl_message("创建文件夹失败: %s", e.what());
        return;
    }

    // 转为本地编码
    std::string u8_name =  "../export/" + table.name + ".txt";
    std::string path = u8_name;
    {
        char local_name[_MAX_PATH] = {0};
        int ret = fl_utf8locale();
        if(!ret){
            fl_utf8to_mb(u8_name.c_str(),u8_name.size(),local_name,sizeof(local_name));
            path = local_name;
        }
    }

    if(std::filesystem::exists(path)){
        fl_message("码表导出失败 文件已存在:%s", u8_name.c_str());
        return;
    }
    
    if(self->_ui_ipc_client.getMsgHelper()->exportCodeTable(table.id, path)) {
        fl_message("码表导出成功至: %s", u8_name.c_str());
    } else {
        fl_message("码表导出失败 可能文件已存在:%s", u8_name.c_str());
    }
}